package br.com.winesys.geta.base;

import java.util.Calendar;
import java.util.Date;

/**
 * Contém rotinas comumente utilizadas nas manipulações de datas.
 * 
 */
public final class DateUtils {

	private DateUtils(){
		
	}
	
	/**
	 * Retorna o primeiro dia do mês da data especificada.
	 * 
	 * @param date 
	 * @return primeiro dia do mês da data especificada.
	 */
	public static Date firstDayOfMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return calendar.getTime();
	}
	
	/**
	 * Retorna o último dia do mês da data especificada.
	 * 
	 * @param date 
	 * @return último dia do mês da data especificada.
	 */
	public static Date lastDayOfMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.MONTH, 1);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return calendar.getTime();
	}
	
	/**
	 * Retorna o primeiro dia do mês anterior à data especificada.
	 * 
	 * @param date 
	 * @return primeiro dia do mês anterior à data especificada.
	 */
	public static Date firstDayOfPreviousMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.MONTH, -1);
		return calendar.getTime();
	}

	/**
	 * Retorna o último dia do mês anterior à data especificada.
	 * 
	 * @param date 
	 * @return último dia do mês anterior à data especificada.
	 */
	public static Date lastDayOfPreviousMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return calendar.getTime();
	}
	
	/**
	 * Retorna o primeiro dia do mês seguinte à data especificada.
	 * 
	 * @param date 
	 * @return primeiro dia do mês seguinte à data especificada.
	 */
	public static Date firstDayOfNextMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.MONTH, 1);
		return calendar.getTime();
	}

	/**
	 * Retorna o último dia do mês seguinte à data especificada.
	 * 
	 * @param date 
	 * @return último dia do mês seguinte à data especificada.
	 */
	public static Date lastDayOfNextMonth(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.MONTH, 2);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return calendar.getTime();
	}
	
	/**
	 * Retorna o número de dias entre duas datas.<p>
	 * 
	 * Obs: O primeiro dia não faz parte da conta.
	 * <i>Ex.: entre os dias 01/JAN e 10/JAN exitem 9 dias</i>   
	 * 
	 * @param firstDay Data inicial 
	 * @param lastDay Data final
	 * @return número de dias entre duas datas
	 */
	public static int daysBetween(Date firstDay, Date lastDay){
		Calendar calendar1 = Calendar.getInstance();
		calendar1.setTime(firstDay);
		calendar1.set(Calendar.HOUR, 0);
		calendar1.set(Calendar.MINUTE, 0);
		calendar1.set(Calendar.SECOND, 0);
		calendar1.set(Calendar.MILLISECOND, 0);
		
		Calendar calendar2 = Calendar.getInstance();
		calendar2.setTime(lastDay);
		calendar2.set(Calendar.HOUR, 0);
		calendar2.set(Calendar.MINUTE, 0);
		calendar2.set(Calendar.SECOND, 0);
		calendar2.set(Calendar.MILLISECOND, 0);
		
		long diffInMilliseconts = calendar2.getTimeInMillis() - calendar1.getTimeInMillis();
		int diffInDays = (int) (diffInMilliseconts / (1000 * 60 * 60 * 24));
		return diffInDays;
	}
}
